package buffer;

import java.util.List;
import java.util.Vector;

import lock.ConcreteLock;
import lock.Lock;

/**
 * The {@link Buffer} class is a threadsafe {@link Source} and {@link Drain}.
 */
public class Buffer<T> implements Source<T>,Drain<T> {
	
	private final List<T> data;
	private final Lock lock;
	private final Lock criticalSection;
	
	/**
	 * Constructor of {@link Buffer}.
	 */
	public Buffer(){
		this.data = new Vector<T>();
		this.lock = new ConcreteLock(true);
		this.criticalSection = new ConcreteLock(false);
	}

	@Override
	public void put(final T object) {
		this.criticalSection.lock();
		this.data.add(object);
		this.lock.unlock();
		this.criticalSection.unlock();
	}

	@Override
	public T get() {
		this.lock.lock();
		this.criticalSection.lock();
		final T result = this.data.remove(0);
		if (!data.isEmpty()) this.lock.unlock();
		this.criticalSection.unlock();
		return result;
	}

	@Override
	public boolean isConstant() {
		return false;
	}
}
